#ifndef _ADAPTIVEPARTITIONER_H_
#define _ADAPTIVEPARTITIONER_H_

#include "job.h"
#include "grid.h"

class AdaptivePartitioner {

//private:
//	/*unique instance of this class*/
//	static AdaptivePartitioner *instance;


public:
	/*Return a single instance of this class*/
	static AdaptivePartitioner *getInstance();
	
	//Constructor
	AdaptivePartitioner(long double granularity_initial, long double granularity_final, long double percentage_startup,
						long double percentage_calisteady, long double variance, int speed_window);
	//Destructor
	~AdaptivePartitioner();
	
	//Parameters
	long double granularity_initial;
	long double granularity_final;
	long double granularity_top;
	long double granularity_bottom;
	long double granularity_previous;
	long double percentage_startup;
	long double percentage_calisteady;
	long double variance;
	int speed_window;
	bool down;
	
	long double granularity_new_heuristic;
	int new_heuristic_count;
	
	//Workload Information
	long double workload_size;
	long double workload_computed;
	long double workload_scheduled;
	
	//Configures the workload
	void configure_workload(long double workload_size, Job *job, Grid *grid);
	
	//Start process
	void start_process();
	
	//When a task finishes its execution, this method must be called to computer the new chunk size
	void task_finished(Task *task, int replica_index);
//	void task_finished(long double task_time, long double task_size);
	
	//Adds a task
	void add_task(long double granularity);
	
	bool workload_completed();
	
	//Phases Constants
	enum { STARTUP, STEADY_STATE, CONCLUSION };
	
	//Dispatches Phases, when the grid speed decrease, three dispatch phase are created to schedule 3 distinct task's size
	enum { MIDDLE, BIG, SMALL };
	
	//The job
	Job *job;
	
	//The Grid
	Grid *grid;
	
	//Array of lasts tasks execution time
	long double *speed_vector;
	
	//Stores the number of tasks execution times in speed vector
	int speed_vector_index;
	
	//Current granularity size
	long double granularity_current;
	
	//Speed of application
	long double speed_current;
	long double speed_previous;
	
	//Current Phase
	int phase_current;
	
	//This method updates the current granularity based in lasts tasks execution time
	void update_granularity(long double task_size);
	
	//This method updates the speed vector queueing it.
	void update_speed_vector(long double task_speed);
	
	//Reset Procs Speeds
	void reset_procs_speeds();

};

#endif //_ADAPTIVEPARTITIONER_H_
